package com.zxq.ruoyi.controller;

import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.servlet.http.HttpServletResponse;

import com.github.pagehelper.PageInfo;
import com.zxq.exchange.EFrame;
import com.zxq.frame.msg.TCPDispatchHandlerFactory;
import com.zxq.ruoyi.domain.IotPacket;
import com.zxq.ruoyi.domain.IotProductFrame;
import com.zxq.ruoyi.domain.vo.IotProductVo;
import com.zxq.ruoyi.domain.vo.PlatformProductVo;
import com.zxq.ruoyi.domain.vo.ProductVoInfo;
import com.zxq.ruoyi.domain.vo.UserOperateVO;
import com.zxq.ruoyi.enums.ECodeEnum;
import com.zxq.ruoyi.enums.EProductState;
import com.zxq.ruoyi.enums.EProtocol;
import com.zxq.ruoyi.service.impl.IotPacketServiceImpl;
import com.zxq.ruoyi.service.impl.IotProductFrameServiceImpl;
import com.zxq.ruoyi.service.impl.IotProductServiceImpl;
import com.zxq.tcp.TcpNetty;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.zxq.ruoyi.domain.IotProduct;
import com.zxq.ruoyi.service.IIotProductService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * 产品Controller
 * 
 * @author ruoyi
 * @date 2022-09-14
 */
@RestController
@RequestMapping("/product")
public class IotProductController extends BaseController
{
    /**
     * 产品服务
     */
    @Autowired
    private IIotProductService iotProductService;

    /**
     * 数据包服务
     */
    @Autowired
    private IotPacketServiceImpl packetService;

    /**
     * 产品协议服务
     */
    @Autowired
    IotProductFrameServiceImpl iotProductFrameService;

    /**
     * 查询产品列表
     */
    @RequiresPermissions("iot:product:list")
    @GetMapping("/list")
    public ProductVoInfo list(IotProduct iotProduct)
    {
        startPage();
        List<IotProduct> list = iotProductService.selectIotProductList(iotProduct);
        List<IotProductVo> iotProductVos = new ArrayList<>();
        for (IotProduct item : list) {
           IotProductVo iotProductVo = new IotProductVo();
           BeanUtils.copyProperties(item,iotProductVo);
           EProductState eProductState = EProductState.getType(item.getState().intValue());
           switch (eProductState){
               case prepare:{
                   iotProductVo.setNextAction("运行");
               }
               break;
               case run: {
                   iotProductVo.setNextAction("停止");
               }
               break;
               case stop:{
                   iotProductVo.setNextAction("就绪");
               }
               break;
           }
            iotProductVos.add(iotProductVo);
        }

        ProductVoInfo rspData = new ProductVoInfo();
        rspData.setCode(200);
        rspData.setRows(iotProductVos);
        rspData.setMsg("查询成功");
        rspData.setTotal((new PageInfo(list)).getTotal());
        List<IotPacket> packets = packetService.selectIotPacketList(new IotPacket());
        rspData.setPacketList(packets);

        return rspData;
    }

    /**
     * 导出产品列表
     */
    @RequiresPermissions("iot:product:export")
    @Log(title = "产品", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, IotProduct iotProduct)
    {
        List<IotProduct> list = iotProductService.selectIotProductList(iotProduct);
        ExcelUtil<IotProduct> util = new ExcelUtil<IotProduct>(IotProduct.class);
        util.exportExcel(response, list, "产品数据");
    }

    /**
     * 获取产品详细信息
     */
    @RequiresPermissions("iot:product:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(iotProductService.selectIotProductById(id));
    }

    /**
     * 新增产品
     */
    @RequiresPermissions("iot:product:add")
    @Log(title = "产品", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody IotProduct iotProduct)
    {
        return toAjax(iotProductService.insertIotProduct(iotProduct));
    }

    /**
     * 修改产品
     */
    @RequiresPermissions("iot:product:edit")
    @Log(title = "产品", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody IotProduct iotProduct)
    {
        return toAjax(iotProductService.updateIotProduct(iotProduct));
    }

    /**
     * 删除产品
     */
    @RequiresPermissions("iot:product:remove")
    @Log(title = "产品", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(iotProductService.deleteIotProductByIds(ids));
    }








    /**
     * netty保存产品id，和task任务的接口
     */
    ConcurrentHashMap<Long, TcpNetty> nettyTask = new ConcurrentHashMap<>();
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(8);

    @PostMapping("startOver")
    public AjaxResult startProjectServer(@RequestBody IotProductVo iotProductVo) {


        Long productId = iotProductVo.getId();
        Integer protocol = iotProductVo.getProtocolType().intValue();
        EProtocol eProtocol = EProtocol.getType(protocol);
        if (eProtocol == EProtocol.TCP) {
            Integer port = iotProductVo.getTransferPort().intValue();
            EProductState productState = EProductState.getType(iotProductVo.getState().intValue());
            switch (productState){
                case prepare:{
                    TcpNetty tcpNetty = new TcpNetty(port);
                    //需要添加分发逻辑
                    IotProductFrame iotProductFrameDo = new  IotProductFrame();
                    iotProductFrameDo.setProductId(productId);

                    List<IotProductFrame> iotProductFrameDoList = iotProductFrameService.selectIotProductFrameList(iotProductFrameDo);
                    iotProductFrameDoList.forEach(item -> {
                        Integer frameType = item.getFrameId().intValue();
                        EFrame eFrame = EFrame.getType(frameType.intValue());
                        tcpNetty.addHandler(TCPDispatchHandlerFactory.create(eFrame));
                    });
                    nettyTask.put(productId, tcpNetty);
                    executorService.execute(tcpNetty);
                    System.out.println(String.format("start product %s ",productId));

                    iotProductVo.setState(EProductState.run.getValue().longValue());
                    iotProductService.updateIotProduct(iotProductVo);
                }
                break;
                case run: {
                    TcpNetty tcpNetty =  nettyTask.get(productId);
                    tcpNetty.cancel();
                    iotProductVo.setState(EProductState.stop.getValue().longValue());
                    iotProductService.updateIotProduct(iotProductVo);
                }
                break;
                case stop:{
                    iotProductVo.setState(EProductState.prepare.getValue().longValue());
                    iotProductService.updateIotProduct(iotProductVo);
                }
                break;

            }

        }
        IotProduct iotProduct = iotProductService.selectIotProductById(iotProductVo.getId());
        BeanUtils.copyProperties(iotProduct,iotProductVo);
        EProductState eProductState = EProductState.getType(iotProduct.getState().intValue());
        switch (eProductState){
            case prepare:{
                iotProductVo.setNextAction("运行");
            }
            break;
            case run: {
                iotProductVo.setNextAction("停止");
            }
            break;
            case stop:{
                iotProductVo.setNextAction("就绪");
            }
            break;
        }
        return AjaxResult.success(iotProductVo);
    }





    @PostMapping("stop")
    public AjaxResult stopProductServer(PlatformProductVo platformProductDTO) {
        Long productId = platformProductDTO.getProductId();
        TcpNetty task = nettyTask.get(productId);
        UserOperateVO<String> resultVO = new UserOperateVO<>();
        if(task == null) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.ProductNoRunTask.getCode());
            resultVO.setMessage(ECodeEnum.ProductNoRunTask.getMsg());
            return AjaxResult.success(resultVO);
        }
        IotProduct iotProductDo = iotProductService.selectIotProductById(productId);
        Long operatorId  = platformProductDTO.getOperatorId();
        if(iotProductDo.getCreator() != operatorId) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.UserNoPermission.getCode());
            resultVO.setMessage(ECodeEnum.UserNoPermission.getMsg());
            resultVO.setData(iotProductDo.getName());
            return AjaxResult.success(resultVO);
        }

        switch (EProductState.getType(iotProductDo.getState().intValue())) {
            case run:{
                task.cancel();
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
                iotProductDo.setState(EProductState.stop.getValue().longValue());
                iotProductService.updateIotProduct(iotProductDo);
                nettyTask.remove(productId);
            }
            break;
            default:{
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
        }
        return AjaxResult.success(resultVO);
    }





}
